#pragma once


#include <Ogre.h>
#include <unordered_map>

#include "Defs.h"
#include "Contact.h"
#include "CollisionData.h"
#include <utility>

//namespace std {
//	
//	template<>
//	class hash<PHYOgre::ShapePair> {
//	public:
//		size_t operator()(const PHYOgre::ShapePair &s) const 
//		{
//			size_t h1 = std::hash<PHYOgre::ShapeType>()(s.first);
//			size_t h2 = std::hash<PHYOgre::ShapeType>()(s.second);
//			return h1 ^ ( h2 << 1 );
//		}
//	};
//}

namespace PHYOgre
{
struct ShapePairHash
{
	std::size_t operator()(const ShapePair &pair)const
	{
		return static_cast<size_t>(pair.first)
           * static_cast<size_t>(LAST)
           + static_cast<size_t>(pair.second);

		
	}
};
class CollisionDetector
{
public:

//	typedef 
	static const int MAX_CONTACT_NUM = 20;

	CollisionDetector(void);
	CollisionDetector(Ogre::SceneManager * iSceneManager);
	~CollisionDetector(void);

	void SetSceneManager(Ogre::SceneManager * iSceneManager);
	
	void GenerateCollisions();
	
	static void HandleCollisionSpherePlane(const Shape* iSphere, const Shape* iPlane,const  IntegrableInterface* obj1,const IntegrableInterface* obj2, CollisionData *iContact);
	static void HandleCollisionPlaneSphere(const Shape* iPlane, const Shape* iSphere,const  IntegrableInterface* obj1,const IntegrableInterface* obj2, CollisionData *iContact);
	static void HandleCollisionSphereSphere(const Shape* iSphere1, const Shape* iSphere2,const  IntegrableInterface* obj1,const IntegrableInterface* obj2, CollisionData *iContact);
	static void HandleCollisionBoxBox(const Shape* iBox1, const Shape* iBox2, const  IntegrableInterface* obj1,const IntegrableInterface* obj2,CollisionData *iContact);
	static void HandleCollisionBoxPlane(const Shape* iBox, const Shape* iPlane, const  IntegrableInterface* obj1,const IntegrableInterface* obj2,CollisionData *iContact);
	static void HandleCollisionPlaneBox(const Shape* iPlane, const Shape* iBox, const  IntegrableInterface* obj1,const IntegrableInterface* obj2,CollisionData *iContact);
	
private:
	typedef void(*CollisionMethod)(const Shape*, const Shape*,const  IntegrableInterface*,const IntegrableInterface* , CollisionData*);
	typedef std::unordered_map<ShapePair, CollisionMethod,ShapePairHash> CollisionMethodsTable;

	
	void RegisterCollisionMethod(ShapePair iShapes, CollisionMethod iMethod);

	Ogre::SceneManager *mSceneManager;
	
	
	CollisionData mCollisionData;
	CollisionMethodsTable mCollisionMethods;
};

}